var ChequeAmount = Base.extend({
	constructor: function() {},
	convert: function(num) {}
});

var ChequeAmountEnglish = ChequeAmount.extend({
	constructor: function() {},

	name1: ['','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT',
		'NINE','TEN','ELEVEN','TWELVE','THIRTEEN','FOURTEEN','FIFTEEN',
		'SIXTEEN','SEVENTEEN','EIGHTEEN','NINETEEN'],
	name2: ['','TEN','TWENTY','THIRTY','FORTY','FIFTY','SIXTY','SEVENTY','EIGHTY','NINETY'],
	name3: ['HUNDRED','THOUSAND','MILLION','BILLION','TRILLION',
		'QUADRILLION','QUINTILLION','SEXTILLION','SEPTILLION','OCTILLION','NONILLION',
		'DECILLION','UNDECILLION','DUODECILLION','TREDECILLION','QUATTUORDECILLION',
		'QUINDECILLION','SEXDECILLION','SEPTENDECILLION','OCTODECILLION',
		'NOVEMDECILLION','VIGINTILLION'],
	maxnum: 65,
	result: '',

	_Number: function(str,p,len)
	{
		var val,rval;
		rval = 0;
		switch(len) {
		case 3:
			if(str.charCodeAt(p) != 48) {
				rval = 1;
				this.result += lib.sprintf("%s HUNDRED",this.name1[str.charCodeAt(p) - 48]);
			}
			++p;
		case 2:
			val = (str.charCodeAt(p+1) - 48) + (str.charCodeAt(p) - 48) * 10;
			if(val) {
				if(rval) this.result += ' ';
				if(val < 20) this.result += this.name1[val];
				else {
					this.result += this.name2[parseInt(val/10)];
					if(val%10) this.result += lib.sprintf("-%s",this.name1[val%10]);
				}
				rval = 1;
			}
			break;
		case 1:
			if(str.charCodeAt(p) != 48) {
				rval = 1;
				this.result += this.name1[str.charCodeAt(p) - 48];
			}
		}
		return rval;
	},
	_Unit: function(str,p,len)
	{
		var off,rval;

		rval = 0;
		if(len > 3) {
			if(len % 3) {
				off = len%3;
				len -= off;
				if(this._Number(str,p,off)) {
					rval = 1;
					this.result += ' ' + this.name3[parseInt(len / 3)] + ' ';
				}
				p += off;
			}
			for(;len > 3;p += 3) {
				len -= 3;
				if(this._Number(str,p,3)) {
					rval = 1;
					this.result += ' ' + this.name3[parseInt(len / 3)] + ' ';
				}
			}
		}
		if(this._Number(str,p,len)) rval = 1;
		return rval;
	},
	convert: function(str)
	{
		var regex = /^(\d+)(\.\d{1,2})?$/
		var parts;

		parts = regex.exec(str);
		if(!parts) return false;

		var flen,len,rval;

		this.result = '';

		if(parts[1].length > this.maxnum ||
		   (parts[2] && parts[2].length > 3)) return false;

		if(parts[2]) parts[2] = parts[2].substr(1);

		if(parts[2] && parts[2].length == 1) {
			parts[2] += '0';
		}
		len = parts[1] ? parts[1].length : 0;
		flen = parts[2] ? parts[2].length : 0;
		rval = len > 0 ? this._Unit(parts[1],0,len) : 0;
		if(rval) {
			if(len == 1 && parts[1].charAt(0) == '1') this.result += ' DOLLAR';
			else this.result += ' DOLLARS';
		}
		if(flen != 0) {
			for(p=0;p<parts[2].length;p++) {
				if(parts[2].charCodeAt(p) != 48) {
					if(rval) this.result += ' AND ';
					if(this._Unit(parts[2],p,flen-p)) {
						if(parts[2] == '01') this.result += ' CENT';
						else this.result += ' CENTS';
						rval = 1;
					}
					break;
				}
			}
		}
		if(!rval) this.result += 'ZERO DOLLARS';
		this.result += ' ONLY';
		return this.result;
	}
});


var ChequeAmountChinese = ChequeAmount.extend({
	constructor: function() {},
	number_name: [0x96f6,0x58f9,0x8cb3,0x53c4,0x8086,0x4f0d,0x9678,0x67d2,0x634c,0x7396],
	units: [
		'',
		[0x62fe], // 拾 1
		[0x4f70], // 佰 2
		[0x4edf], // 仟 3
		[0x842c],null,null,null, // 萬 4
		[0x5104],null,null,null, // 億 8
		[0x5146],null,null,null, // 兆 12
		[0x4eac],null,null,null, // 京 16
		[0x5793],null,null,null, // 垓 20
		[0x79ed],null,null,null, // 秭 24
		[0x7a70],null,null,null, // 穰 28
		[0x6e9d],null,null,null, // 溝 32
		[0x6f97],null,null,null, // 澗 36
		[0x6b63],null,null,null, // 正 40
		[0x8f09],null,null,null, // 載 44
		[0x6975],null,null,null, // 極 48
		[0x6052,0x6cb3,0x6c99],null,null,null, // 恒河沙 52
		[0x963f,0x50e7,0x7947],null,null,null, // 阿僧祇 56
		[0x90a3,0x7531,0x4ed6],null,null,null, // 那由他 60
		[0x4e0d,0x53ef,0x601d,0x8b70],null,null,null, // 不可思議 64
		[0x7121,0x91cf,0x5927,0x6578],null,null,null // 無量大數 68
	],
	one_ten: [0x58f9,0x62fe],
	dollar: [0x5143],
	tencent: [0x89d2],
	cent: [0x4ed9],
	only: [0x6b63],
 
	convert: function(str)
	{
		var regex = /^(\d+)(\.\d{1,2})?$/
		var parts = regex.exec(str);

		if(!parts) return false;

		if(parts[2]) {
			parts[2] = parts[2].substr(1);
			if(parts[2].length == 1) parts[2] += '0';
		}
		var result = '';

		Debug.present && Debug.trace(1,"ChequeAmountChinese: parts=(%s)",parts);

		regex = /^0+$/
		if(parts[1].match(regex)) {
			if(!parts[2] || parts[2].match(regex)) {
				result += lib.utf16char(this.number_name[0]);
				result += lib.utf16str(this.dollar);
			}
		}
		else {
			var remain;
			var i,ch,pos,lastunit;
	
			result = '';
			lastunit = false;
			for(i=0;i<parts[1].length;i++) {
				pos = parts[1].length - i - 1;
				ch = parts[1].charCodeAt(i);
				ch -= 48;
				if(ch != 0) {
					result += lib.utf16char(this.number_name[ch]);
					lastunit = false;
				}
				if(pos >= this.units.length) return false;
	
				if(this.units[pos] != null) {
					if(ch != 0 || pos%4 == 0) {
						if(!lastunit) result += lib.utf16str(this.units[pos]);
						lastunit = true;
					}
				}
				else {
					remain = pos%4;
					if(ch != 0) {
						result += lib.utf16str(this.units[remain]);
						lastunit = false;
					}
				}
			}
			result = result.replace(lib.utf16str(this.one_ten),lib.utf16char(this.units[1]));
			result += lib.utf16str(this.dollar);
		}
		if(parts[2]) {
			var s = parts[2];
			var ch1 = s.charCodeAt(0) - 48;
			var ch2 = s.charCodeAt(1) - 48;

			if(ch1 != 0) {
				result += lib.utf16char(this.number_name[ch1]);
				result += lib.utf16str(this.tencent);
			}
			if(ch2 != 0) {
				result += lib.utf16char(this.number_name[ch2]);
				result += lib.utf16str(this.cent);
			}
		}
		else result += lib.utf16char(this.only);
		return result;
	}
});

// Modified from bsdgames
var ChequeInputMethod = InputMethod.extend({
	style_array: null,
	style_result: null,
	target_list: 'ShiftNum',
	menu_node: null,
	default_style: 0,
	candlist: null,

	constructor: function()
	{
		var x = this;
		var menu_handler = function(pos) { x.default_style = pos; return true; }

		this.style_array = new Array();
		this.style_array[0] = new ChequeAmountEnglish;
		this.style_array[1] = new ChequeAmountChinese;

		this.menu_node = new GFMenuNode('Cheque');
		this.menu_node.SetItem(0,$GFS('Amount in English first'),menu_handler);
		this.menu_node.SetItem(1,$GFS('Amount in Chinese first'),menu_handler);
	},
	IMName: function()
	{
		return 'Cheque Amount';
	},
	GetLanguage: function()
	{
		return 'account';
	},
	GetMenuNode: function()
	{
		return this.menu_node;
	},
	SuggestionType: function()
	{
		return null;
	},
	keydown_handler: function(obj,key,m)
	{
		if(key == 8) {
			if(this.ime.GetPreeditLength() > 0) {
				this.ime.DeletePreedit(1,1);
				this.Update();
				return false;
			}
			else return true;
		}
		else if(key == 190 || key == 110) {
			this.ime.AppendPreedit('.','.');
			return false;
		}
		return true;
	},
	keypress_handler: function(obj,key)
	{
		if(key == 27) { // escape
			this.ime.ResetPreedit();
			return false;
		}
		else if(key == 32) { // complete
			if(this.candlist) {
				this.candlist.onSelectCandidate(obj,1);
				return false;
			}
			else return true;
		}
		else if(48 <= key && key <= 57) { // 0-9
			var ch = String.fromCharCode(key);
			this.ime.AppendPreedit(ch,ch);
			this.Update();
			return false;
		}
		else return true;
	},
	onActive: function()
	{
		this.current_list = null;
	},
	onDeactive: function()
	{
		this.current_list = null;
	},
	Update: function()
	{
		this.current_pos = 0;
		if(this.ime.GetPreeditLength() > 0) {
			var preedit = this.ime.GetPreedit();
			var i,j,style,str;
	
			this.style_result = new Array();
			j = 0;
			// check default style first
			style = this.style_array[this.default_style];
			str = style.convert(preedit);
			if(str) this.style_result[j++] = str;

			for(i=0;i<this.style_array.length;i++) {
				// skip default style
				if(i == this.default_style) continue;
				style = this.style_array[i];

				str = style.convert(preedit);
				if(str) this.style_result[j++] = str;
			}
			this.UpdateCandidate();
		}
		else {
			this.style_result = null;
			this.UpdateCandidate();
		}
	},
	ListSelectHandler: function(obj,pos)
	{
		this.ime.SendString(obj,this.style_result[pos]);
		this.style_result = null;
		this.ime.ResetPreedit();
		return true;
	},
	UpdateCandidate: function()
	{
		var x = this;

		if(this.style_result && this.style_result.length > 0) {
			if(this.candlist) {
				this.candlist.UpdateList(this.style_result);
			}
			else {
				this.candlist = this.ime.candwin.OccupyList(this,this.target_list);
				if(!this.candlist) return;

				this.candlist.SetList(null,this.style_result,function(obj,pos) { return x.ListSelectHandler(obj,pos); });
				this.candlist.SetCancelHandler(function() { x.candlist = null; return true; });
			}
			this.ime.candwin.SetStatus(null);
		}
		else {
			this.ime.candwin.ReleaseList(this,this.target_list);
			this.candlist = null;
			this.ime.candwin.SetStatus($GFS('The amount is too large.'));
		}
		this.ime.candwin.UpdateCandidate();
	}
});


